package com.cellulam.framework.fs.excel.reader;

import com.cellulam.framework.fs.excel.model.RowNumber;
import com.google.common.collect.Lists;
import com.cellulam.framework.fs.excel.model.ExcelFieldMeta;
import com.cellulam.framework.fs.excel.utils.CellUtils;
import com.cellulam.framework.fs.excel.utils.ExcelMetaUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.security.InvalidParameterException;
import java.util.Iterator;
import java.util.List;

/**
 * 按 table 读取
 */
public class SimpleTableReader {

    private static final Logger logger = LoggerFactory.getLogger(SimpleTableReader.class);

    private Workbook workbook;

    public SimpleTableReader(Workbook workbook) {
        this.workbook = workbook;
    }

    /**
     * 转换为固定类
     *
     * @param excelClass
     * @param sheetNo
     * @param startRow
     * @param <T>
     * @return
     */
    public <T extends RowNumber> List<T> readAsList(Class<T> excelClass, int sheetNo, int startRow) {
        Sheet sheet = workbook.getSheetAt(sheetNo);
        if (sheet == null) {
            throw new InvalidParameterException(String.format("sheet %s not found", sheetNo));
        }

        List<ExcelFieldMeta> fieldInfos = ExcelMetaUtils.readExcelProperty(excelClass);
        if (CollectionUtils.isEmpty(fieldInfos)) {
            throw new InvalidParameterException(String.format("excelClass %s has no fields", excelClass.getName()));
        }

        List<T> items = Lists.newArrayList();
        for (int rowNum = startRow; rowNum < sheet.getLastRowNum() + 1; rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            T item = newBean(excelClass);
            for (ExcelFieldMeta fieldInfo : fieldInfos) {
                Object fieldValue = ExcelMetaUtils.getFieldValue(fieldInfo, row.getCell(fieldInfo.getIndex()));
                try {
                    fieldInfo.getRawField().set(item, fieldValue);
                } catch (Exception e) {
                    logger.error("set field {} value failure", fieldInfo.getRawField().getName(), e);

                }
            }
            item.setRow(rowNum + 1);
            items.add(item);
        }

        return items;
    }

    /**
     * 用文本读取
     *
     * @param sheetNo  0-base
     * @param startRow
     * @return
     */
    public List<List<String>> readAsStringRows(int sheetNo, int startRow) {
        Sheet sheet = workbook.getSheetAt(sheetNo);
        if (sheet == null) {
            throw new InvalidParameterException(String.format("sheet %s not found", 1));
        }

        List<String> headers = null;
        List<List<String>> items = Lists.newArrayList();
        for (int rowNum = startRow; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            List<String> r = Lists.newArrayList();
            if (headers == null) {
                Iterator<Cell> iter = row.cellIterator();
                while (iter.hasNext()) {
                    Cell cell = iter.next();
                    r.add(CellUtils.toText(cell));
                }
                headers = r;
            } else {
                for (int i = 0; i < headers.size(); i++) {
                    r.add(CellUtils.toText(row.getCell(i)));
                }
            }

            items.add(r);
        }
        return items;
    }

    private <T extends RowNumber> T newBean(Class<T> excelClass) {
        try {
            return excelClass.newInstance();
        } catch (Exception e) {
            logger.error("new instance {} failure", excelClass.getName(), e);
            throw new RuntimeException(e);
        }
    }

}
